概述
本篇介紹Spring frameowrk與資料庫存取的子專案: Spring Data 的使用方式,並且說明本專案連接及存取MongoDB的程式說明。涵蓋2個主要部分:
- Spring Data 介紹
- Repository 與 Template概念及程式碼舉例
Spring Data
Spring Data是Spring Framework的一個子專案,專注於簡化各種資料庫的存取方式,包括關連式資料庫(如 MySQL、PostgreSQL)和NoSQL(如 MongoDB)資料庫。目的是透過抽象化提供統一的資料存取方法,讓開發者能夠以簡單的方式實現複雜的資料操作。
抽象化
所謂抽象化,就是把實作和商業邏輯分離,可以大致理解成我們在討論IoC的好處時提到的: "解掉主流程與依賴的耦合,方便依賴抽換"。以Java的說法來看,這類設計強調"以介面來撰寫商業邏輯,而不是具體的實作"。
- 再更實直白一點來說,有無抽象化的程式流程差別如下:
// 非抽象化
1.使用JSON Parser處理事件 -> 2.將處理好的事件存進MongoDB
// 抽象化
1.處理事件,2.將處理好的事件存進某資料庫
(但底層的資料庫實作可以隨時新增或替換)
Spring Boot連DB的Coding style
- 不同於一般Java程式連接資料庫的過程,使用Spring開發的模式將許多傳統由開發者手動處理的部分自動化,讓開發者可以專注在商業邏輯的實現上。需要習慣一下跟過往什麼都自己來比較不一樣的Coding模式。
- Spring和開發者的分工大致如下:
- Spring 負責的部分:
- 取得Connection、準備prepareStatement,到關閉connection這些工作都是。
- 開發者需處理的部分:
下面這張官方的表列出了哪些事情是Spring或者開發人員要負責的部分:
存取資料庫的兩種方式: Template API 及Repository
- 根據不同抽象層級,在Spring生態系大致可分為Template 和 Repository兩種。不同方法間可以混用。
- 無論採用哪種方式,設置資料來源(DataSource)都是首要的步驟,因為資料庫操作的基礎依賴於這個連接配置。
Template API: 以Spring Data MongoDB為例
- Spring Data為各種資料庫操作,定義了型別為Operation的介面,例如,對於MongoDB,Spring Data 提供了MongoOperations介面;對於Redis,則有RedisOperations。
- Template則是Operations介面的實作。開發者可以直接使用Template提供的方法來操作資料庫,也可以根據需求自定義這些操作。
- 以本專案寫入MongoDB的Collection:
action_record
為例,需要準備如下:
設定相關Bean:MongoClient及mongoTemplate,並且在外部檔案設定連線資訊
public class MongoConfig {
// 從外部設定檔案拿到連線資訊
@Value("${spring.data.mongodb.uri}")
String monogoUri;
public @Bean MongoClient mongoClient() {
return MongoClients.create(monogoUri);
}
@Bean
MongoTemplate mongoTemplate(MongoClient mongoClient) {
return new MongoTemplate(mongoClient, "nextpage");
}
}
設定Document Class
- Class MessageContentTrainingLog
@Document("action_record")
public class MessageContentTrainingLog extends MessageContent {
public String userId;
public String action;
public String actionType;
public Integer weight;
public Integer repetition;
public Integer set;
public Integer percentagOfRepetitionMaximum;
public String date;
}
- @Document表示要寫入MongoDB的Document Schema,可以看到我們直接拿之前在講解反序列化時,設定給Jackson ObjectMapper的Class的作為Document Class。
- @Document中可以指定要寫入的Collection為
action_record
。
Query Function
- 需要insert資料時,只需要使用mongoTemplate內建的function,並指定反序列化後的Document Class的Object即可:
mongoTemplate.insert(messageContent);
Repository: 以Spring Data JDBC查詢關連式資料庫為例
- Repository以Template為基礎,更為高階的抽象層。
- Spring Data JDBC包裝了JDBC,讓Spring去連接到資料庫。準備步驟很間單:
- 1.在pom.xml的Dependency加入spring-boot-starter-data-jdbc,
- 注意: 是starter,而不是spring-data, 也不是spring-boot-starter-jdbc
- 2.在pom.xml的Dependency要加入想要連接的資料庫的JDBC Driver
- 3.單純使用一個Property檔案設定Data Source,或者透過Bean指定Data Source的設定檔案。
使用外部Property檔案設定Data Source
- 如果整個程式只有一個Data source,直接在application.properties設定即可,不用做任何事:
- application.properties
spring.datasource.url=資料庫的連線位址
spring.datasource.username=帳號
spring.datasource.password=密碼
使用Bean指定Data Source的設定來源
@Bean
@ConfigurationProperties(prefix = "app.datasource")
public SomeDataSource dataSource() {
return new SomeDataSource();
}
}
- 只要dependency有spring-boot-starter-data-jdbc和JDBC driver,他預設就會去建立Data source和所需要的實例,並套用開發者在外部Property檔案或者Bean設定的參數。
- 只要設好參數,auto configure會把需要的bean做好,就可以順利連上DB。
Query Function
- 我們可以改寫
spring-boot-starter-data-jdbc
提供的Repository Interface,來撰寫Query用的Function:
public interface UserProjectRepository extends CrudRepository<UserProject, Long> {
@Query("select project_name, base_weight from UserProject u where u.line_id = :lineId")
UserProject findByLineId(@Param("line_id") String lineId);
}
- CrudRepository是spring-boot-starter-data-jdbc提供的介面,根據不同的資料庫對象,我們可以改寫不同的介面,來達到我們對各種資料庫的查詢需求。
結論
- 本篇文章說明Spring Data基本的觀念及使用風格,包含了RepositoryTemplate API,及並提供簡單的範例來寫入資料到指定的Collection。
- 本專案會使用MongoDB來記錄經過分析後的使用者資訊,以及Open AI針對訊息的回應。
- 使用Template API時,需要註冊MongoClient、MongoTemplate,以及@Document的Bean,並且在外部檔案設定連線資訊。就可以MongoTemplate實例來對MongoDB做存取。
下一篇將回到我們程式運行的EC2,介紹如何使用Docker來部署MongoDB服務